const path = require('path');
const fs = require('fs');
const process = require('process');
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const TerserPlugin = require("terser-webpack-plugin");
const ESLintPlugin = require('eslint-webpack-plugin');
const CopyPlugin = require("copy-webpack-plugin");
const safePostCssParser = require('postcss-safe-parser');
const postcssNormalize = require('postcss-normalize');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const publicUrlOrPath = getPublicUrlOrPath(
    process.env.NODE_ENV === 'development',
    require(resolveApp('package.json')).homepage,
    process.env.PUBLIC_URL
);
const publicPath = './public';
const appHtml = `${publicPath}/index.html`;
const outputPath = 'dist';
const imageInlineSizeLimit = parseInt(
    process.env.IMAGE_INLINE_SIZE_LIMIT || '10000'
);
// Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
function resolvePath(dir) {
    return path.join(__dirname, dir);
}

module.exports = function (webpackEnv) {
    const isEnvDevelopment = webpackEnv === 'development';
    const isEnvProduction = webpackEnv === 'production';
    const isEnvProductionProfile = isEnvProduction && process.argv.includes('--profile');
    // common function to get style loaders
    const getStyleLoaders = (cssOptions, preProcessor) => {
        const loaders = [
            isEnvDevelopment && require.resolve('style-loader'),
            isEnvProduction && {
                loader: MiniCssExtractPlugin.loader,
                // css is located in `static/css`, use '../../' to locate index.html folder
                // in production `paths.publicUrlOrPath` can be a relative path
                options: paths.publicUrlOrPath.startsWith('.') ? {
                    publicPath: '../../'
                } : {},
            },
            {
                loader: require.resolve('css-loader'),
                options: cssOptions,
            },
            {
                // Options for PostCSS as we reference these options twice
                // Adds vendor prefixing based on your specified browser support in
                // package.json
                loader: require.resolve('postcss-loader'),
                options: {
                    // Necessary for external CSS imports to work
                    // https://github.com/facebook/create-react-app/issues/2677
                    ident: 'postcss',
                    plugins: () => [
                        require('postcss-flexbugs-fixes'),
                        require('postcss-preset-env')({
                            autoprefixer: {
                                flexbox: 'no-2009',
                            },
                            stage: 3,
                        }),
                        // Adds PostCSS Normalize as the reset css with default options,
                        // so that it honors browserslist config in package.json
                        // which in turn let's users customize the target behavior as per their needs.
                        postcssNormalize(),
                    ],
                    sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
                },
            },
        ].filter(Boolean);
        if (preProcessor) {
            loaders.push({
                loader: require.resolve('resolve-url-loader'),
                options: {
                    sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
                    root: paths.appSrc,
                },
            }, {
                loader: require.resolve(preProcessor),
                options: {
                    sourceMap: true,
                },
            });
        }
        return loaders;
    };
    return {
        mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
        devtool: isEnvProduction ? 'none' : isEnvDevelopment && 'cheap-module-source-map',
        entry: './src/index.js',
        output: {
            path: path.resolve(__dirname, outputPath),
            filename: 'static/js/[name].[hash:8].js',
            // this defaults to 'window', but by setting it to 'this' then
            // module chunks which are built will work in web workers as well.
            chunkFilename: isEnvProduction ? 'static/js/[name].[contenthash:8].chunk.js' : isEnvDevelopment && 'static/js/[name].chunk.js',
            globalObject: 'this'
        },
        optimization: {
            minimize: isEnvProduction,
            minimizer: [
                // 由于老牌工具uglify不支持es6，且uglify-es不再更新，我们选择terser作为js代码压缩工具。
                new TerserPlugin({
                    parallel: true,    //使用多进程并发运行
                    // https://github.com/terser/terser#minify-options
                    terserOptions: {
                        parse: {
                            ecma: 8,
                        },
                        compress: {
                            ecma: 5,
                            warnings: false,
                            comparisons: false,
                            // Disabled because of an issue with Terser breaking valid code:
                            // https://github.com/facebook/create-react-app/issues/5250
                            // Pending further investigation:
                            // https://github.com/terser-js/terser/issues/120
                            inline: 2,
                        },
                        mangle: {
                            safari10: true,
                        },
                        // Added for profiling in devtools
                        keep_classnames: isEnvProductionProfile,
                        keep_fnames: isEnvProductionProfile,
                        output: {
                            ecma: 5,
                            comments: false,
                            // Turned on because emoji and regex is not minified properly using default
                            // https://github.com/facebook/create-react-app/issues/2488
                            ascii_only: true,
                        },
                    },
                    sourceMap: shouldUseSourceMap,
                    extractComments: true
                }),
                // This is only used in production mode
                new OptimizeCSSAssetsPlugin({
                    cssProcessorOptions: {
                        parser: safePostCssParser,
                        map: shouldUseSourceMap ? {
                            // `inline: false` forces the sourcemap to be output into a
                            // separate file
                            inline: false,
                            // `annotation: true` appends the sourceMappingURL to the end of
                            // the css file, helping the browser find the sourcemap
                            annotation: true,
                        } : false,
                    },
                    cssProcessorPluginOptions: {
                        preset: ['default', {
                            minifyFontValues: {
                                removeQuotes: false
                            }
                        }],
                    },
                })
            ],
            splitChunks: {
                chunks: 'all',
                name: isEnvDevelopment,
                minSize: 204800
            },
            runtimeChunk: {
                name: entrypoint => `runtime-${entrypoint.name}`
            }
        },
        resolve: {
            alias: {
                '@imgs': resolvePath('src/imgs'),
                '@icon': resolvePath('src/icon'),
                '@compa': resolvePath('src/components/basic'),
                '@compb': resolvePath('src/components/business'),
                '@page': resolvePath('src/pages'),
                '@util': resolvePath('src/utils'),
                '@api': resolvePath('src/utils/api')
            }
        },
        module: {
            rules: [
                // "postcss" loader applies autoprefixer to our CSS.
                // "css" loader resolves paths in CSS and adds assets as dependencies.
                // "style" loader turns CSS into JS modules that inject <style> tags.
                // In production, we use MiniCSSExtractPlugin to extract that CSS
                // to a file, but in development "style" loader enables hot editing
                // of CSS.
                // By default we support CSS Modules with the extension .module.css
                // {
                //     test: cssRegex,
                //     exclude: cssModuleRegex,
                //     use: getStyleLoaders({
                //         importLoaders: 1,
                //         sourceMap: isEnvProduction ?
                //             shouldUseSourceMap : isEnvDevelopment,
                //     }),
                //     // Don't consider CSS imports dead code even if the
                //     // containing package claims to have no side effects.
                //     // Remove this when webpack adds a warning or an error for this.
                //     // See https://github.com/webpack/webpack/issues/6571
                //     sideEffects: true,
                // },
                // Adds support for CSS Modules (https://github.com/css-modules/css-modules)
                // using the extension .module.css
                // {
                //     test: cssModuleRegex,
                //     use: getStyleLoaders({
                //         importLoaders: 1,
                //         sourceMap: isEnvProduction ?
                //             shouldUseSourceMap : isEnvDevelopment,
                //         modules: {
                //             getLocalIdent: getCSSModuleLocalIdent,
                //         },
                //     }),
                // },
                {
                    test: /.css$/,
                    use: ['style-loader', 'css-loader']
                },
                {
                    test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
                    loader: require.resolve('url-loader'),
                    options: {
                        limit: imageInlineSizeLimit,
                        name: 'static/media/[name].[hash:8].[ext]',
                    },
                },
                {
                    loader: 'url-loader?limit=100000',
                    test: /\.(png|woff|woff2|eot|ttf|svg)$/
                },
                // "file" loader makes sure those assets get served by WebpackDevServer.
                // When you `import` an asset, you get its (virtual) filename.
                // In production, they would get copied to the `build` folder.
                // This loader doesn't use a "test" so it will catch all modules
                // that fall through the other loaders.
                // {
                //     loader: require.resolve('file-loader'),
                //     // Exclude `js` files to keep "css" loader working as it injects
                //     // its runtime that would otherwise be processed through "file" loader.
                //     // Also exclude `html` and `json` extensions so they get processed
                //     // by webpacks internal loaders.
                //     exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
                //     options: {
                //         name: 'static/media/[name].[hash:8].[ext]',
                //     },
                // },
                {
                    test: /\.js/,
                    exclude: /node_modules/,
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: ["@babel/preset-env", "@babel/preset-react"]
                        }
                    }
                }
            ]
        },
        plugins: [
            new webpack.HotModuleReplacementPlugin(),
            new HtmlWebpackPlugin({
                filename: 'index.html',
                template: appHtml,
                minify: {
                    removeComments: true,
                    collapseWhitespace: true,
                    removeRedundantAttributes: true,
                    useShortDoctype: true,
                    removeEmptyAttributes: true,
                    removeStyleLinkTypeAttributes: true,
                    keepClosingSlash: true,
                    minifyJS: true,
                    minifyCSS: true,
                    minifyURLs: true,
                }
            }),
            new MiniCssExtractPlugin({
                // Options similar to the same options in webpackOptions.output
                // both options are optional
                filename: 'static/css/[name].[contenthash:8].css',
                chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
            }),
            // Automatically clean last build files
            new CleanWebpackPlugin(),
            new webpack.optimize.MinChunkSizePlugin({
                minChunkSize: 10240, // Minimum number of characters
            }),

        ],
        // Turn off performance processing because we utilize
        // our own hints via the FileSizeReporter
        performance: false

    };
};